/*
 *
 *  * Copyright:  2018 smarabbit studio.
 *  *
 *  *  Licensed under the Confluent Community License; you may not use this file
 *  *  except in compliance with the License.  You may obtain a copy of the License at
 *  *
 *  *  http://www.confluent.io/confluent-community-license
 *  *
 *  *  Unless required by applicable law or agreed to in writing, software
 *  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  *  specific language governing permissions and limitations under the License.
 *  *
 *  *  @作   者： 黄开晖 (117227773@qq.com)
 *  *  @日   期:    ${DATE}
 *
 */

package com.massyframework.beanskin.launching.web.jetty;

import java.util.Objects;

import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;

import com.massyframework.beanskin.framework.FrameworkConfig;
import com.massyframework.beanskin.launching.web.J2eeEnvironmentSetter;
import com.massyframework.beanskin.web.context.ServletContextWrapper;

final class JettyServerBuilder {

    private int port = 8080;
    private String host = "localhost";

    private String resourceBase;
    private String contextPath = "/";

    private int mixNumber = 10;
    private int maxNumber = 100;

    /**
     * 设置主机
     *
     * @param value {@link String}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder host(String value) {
        this.host = value;
        return this;
    }

    /**
     * 设置端口
     *
     * @param value {@link int}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder port(int value) {
        this.port = value;
        return this;
    }

    /**
     * 设置资源目录
     *
     * @param value {@link String}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder resourceBase(String value) {
        this.resourceBase = value;
        return this;
    }


    /**
     * 设置上下文路径
     *
     * @param value {@link String}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder contextPath(String value) {
        this.contextPath = value;
        return this;
    }

    /**
     * 最小线程数
     *
     * @param value {@link int}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder mixThreadNumber(int value) {
        this.mixNumber = value;
        return this;
    }

    /**
     * 最大线程数
     *
     * @param value {@link int}
     * @return {@link JettyServerBuilder}
     */
    public JettyServerBuilder maxThreadNumber(int value) {
        this.maxNumber = value;
        return this;
    }

    /**
     * 创建Jetty服务
     *
     * @return {@link Server}
     */
    public Server build(FrameworkConfig config) throws Exception {
        Objects.requireNonNull(this.resourceBase, "\"resourceBase\" cannot be null.");

        Server result = new Server(this.createThreadPool());
        WebAppContext context = new WebAppContext();

        //ServletContextHandler context = new ServletContextHandler(
        //        ServletContextHandler.SESSIONS);
        context.setContextPath(this.contextPath);
        context.setResourceBase(this.resourceBase);
        context.setGzipHandler(new GzipHandler());
        context.getServletContext().setExtendedListenerTypes(true);

        ClassLoader classLoader = this.getClass().getClassLoader();
        context.setClassLoader(classLoader);

        result.setHandler(context);
        result.addConnector(this.createConnector(result));
        
        // WebSocket初始化
        ServletContextHandler servletContextHandler =
        		WebAppContext.getServletContextHandler(context.getServletContext());
        WebSocketServerContainerInitializer.initialize(servletContextHandler);   
       
        ServletContextWrapper wrapper = new JettyServletContextAdapter(context);
        J2eeEnvironmentSetter setter = new J2eeEnvironmentSetter(wrapper);
        setter.accept(config);
        
        return result;
    }

    /**
     * 创建线城池
     *
     * @return {@link ThreadPool}
     */
    private ThreadPool createThreadPool() {
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setMinThreads(this.mixNumber);
        threadPool.setMaxThreads(this.maxNumber);
        return threadPool;
    }

    /**
     * 创建网络链接器
     * @param server
      * @return
     */
    private NetworkConnector createConnector(Server server) {
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(port);
        connector.setHost(host);
        return connector;
    }

}
